package org.lfh.wintersun.web.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.lfh.wintersun.common.base.PageUtils;
import org.lfh.wintersun.redis.BloomFilterInitializer;
import org.lfh.wintersun.web.user.dao.SysUserDao;
import org.lfh.wintersun.web.user.dto.SysUserDTO;
import org.lfh.wintersun.web.user.entity.SysUserEntity;
import org.lfh.wintersun.web.user.service.SysUserService;
import org.redisson.api.RBloomFilter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 用户信息(SysUser)表服务实现类
 *
 * @author lfh
 * @since 2024-10-10 15:35:10
 */
@Service("sysUserService")
public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> implements SysUserService {

    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private BloomFilterInitializer bloomFilterInitializer;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
//    public SysUserEntity queryById(Long id) {
//        String userStr = redisTemplate.opsForValue().get("user:id:" + id);
//        if (StrUtil.isNotBlank(userStr)) {
//            return BeanUtil.toBean(userStr, SysUserEntity.class);
//        }
//        SysUserEntity user = this.getById(id);
//        if (Objects.nonNull(user)) {
//            redisTemplate.opsForValue().set("user:id:" + id, JSONUtil.toJsonStr(user));
//        } else {
//            // 缓存空值，避免缓存穿透,存在一下2个缺点
//            //1.浪费内存，保存了无意义的值
//            //2.可能导致短期数据不一致。例如：线程A查询id=10，缓存空值；线程B插入id=10的数据但未更新缓存；线程C查询id=10，仍获取空值
//            redisTemplate.opsForValue().set("user:id:" + id, "", 30, TimeUnit.SECONDS);
//        }
//        return user;
//    }
    public SysUserEntity queryById(Long id) {
        // 布隆过滤器检查
        RBloomFilter<Long> userBloomFilter = bloomFilterInitializer.getUserBloomFilter();
        if (!userBloomFilter.contains(id)) {
            return null; // 布隆过滤器判断ID不存在，直接返回空值
        }
        String userStr = redisTemplate.opsForValue().get("user:id:" + id);
        if (StrUtil.isNotBlank(userStr)) {
            if (userStr.isEmpty()) {
                return null;
            }
            SysUserEntity user = JSONUtil.toBean(userStr, SysUserEntity.class);
            return user;
        }
        SysUserEntity user = this.getById(id);
        if (Objects.nonNull(user)) {
            // 将查询结果存入缓存
            redisTemplate.opsForValue().set("user:id:" + id, JSONUtil.toJsonStr(user), 30, TimeUnit.SECONDS);
        } else {
            // 缓存空值，避免缓存穿透
            redisTemplate.opsForValue().set("user:id:" + id, "", 30, TimeUnit.SECONDS);
        }

        return user;
    }

    /**
     * 分页查询
     *
     * @param sysUserDTO 参数
     * @return 查询结果
     */
    @Override
    public PageUtils<SysUserEntity> queryByPage(SysUserDTO sysUserDTO) {
        IPage<SysUserEntity> iPage = this.baseMapper.queryAllByLimit(new Page<>(sysUserDTO.getPage(), sysUserDTO.getLimit()));
        return new PageUtils<>(iPage);
    }

    /**
     * 新增数据
     *
     * @param sysUserEntity 实例对象
     * @return 实例对象
     */
    @Override
    public SysUserEntity insert(SysUserEntity sysUserEntity) {
        this.save(sysUserEntity);
        redisTemplate.opsForValue().set("user:id:" + sysUserEntity.getId(), JSONUtil.toJsonStr(sysUserEntity));
        bloomFilterInitializer.getUserBloomFilter().add(sysUserEntity.getId());
        return sysUserEntity;
    }

    /**
     * 修改数据
     *
     * @param sysUserEntity 实例对象
     * @return 实例对象
     */
    @Override
    public SysUserEntity update(SysUserEntity sysUserEntity) {
        this.updateById(sysUserEntity);
        return sysUserEntity;
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     */
    @Override
    public void deleteById(Long id) {
        this.removeById(id);
    }

    @Override
    public SysUserEntity findByUsername(String userName) {
        LambdaQueryWrapper<SysUserEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUserEntity::getLoginName, userName);
        return this.getOne(queryWrapper);
    }
}
